package com.bawei.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.bawei.config.Alipay;
import com.bawei.pojo.Indent;
import com.bawei.pojo.Order;
import com.bawei.service.IndentService;
import com.bawei.service.OrderService;
import com.bawei.service.PayService;
import com.bawei.bean.AliPayBean;
import com.bawei.util.SnowFlakeUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Controller
@RequestMapping("/ali")
public class PayController {

    /**日志对象*/
    private static final Logger logger = LoggerFactory.getLogger(OrderController.class);

    @Autowired
    private PayService payService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private OrderService orderService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private IndentService indentService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private Alipay alipay;

    @Autowired
    private RedissonClient redissonClient;

    @RequestMapping("/pay")
    @ResponseBody
    public String alipay(String outTradeNo, String subject, String totalAmount, String body,Integer middleId) throws AlipayApiException {

        ValueOperations<String, String> ops = redisTemplate.opsForValue();

        //加分布式锁
        RLock goods = redissonClient.getLock("goods");
        goods.lock();

        //从redis获取到库存量
        String limit = ops.get("goods" + middleId);
        Order order = orderService.getMiddleId(middleId);
        //如果redis中没有数据，则把数据添加到redis
        if (limit==null){
            Integer num = order.getLimitNum();
            ops.set("goods"+middleId, String.valueOf(num));
        }

        try {
            Integer limitNum = Integer.valueOf(limit);
            //修改商品存量-1
            if (limitNum>0){
                //给redis的库存量重新赋值，让库存量-1
                ops.set("goods"+middleId,limitNum-1+"");
                logger.info("商品{},库存量:{}",order.getGoodsName(),(limitNum-1));
                Integer i =  orderService.updateLimitNum(middleId);
                //只有修改数量成功以后才能够添加订单，防止发生超买，重复下单
                if (i>0){
                    //雪花算法随机生成订单编号
                    Long snowFlakeId = SnowFlakeUtil.getSnowFlakeId();
                    //添加到订单信息
                    Integer orderId = payService.addOrder(middleId,snowFlakeId);
                    //添加到延迟队列中
                    rabbitTemplate.convertAndSend("delayed.exchange","delayed.routingkey",String.valueOf(orderId),msg->{
                        //设置1分钟过期时间
                        msg.getMessageProperties().setDelay(60000);
                        return msg;
                    });
                    outTradeNo = String.valueOf(snowFlakeId);
                    //调用支付宝接口
                    logger.info("商户订单号为{},订单名称为{},付款金额为{},商品描述{}", outTradeNo, subject, totalAmount, body);
                    AliPayBean alipayBean = new AliPayBean();
                    alipayBean.setOut_trade_no(outTradeNo);
                    alipayBean.setSubject(subject);
                    alipayBean.setTotal_amount(totalAmount);
                    alipayBean.setBody(body);
                    return payService.aliPay(alipayBean);
                }else {
                    return "修改失败";
                }
            }else {
                return "商品已卖完";
            }
        }finally {
            goods.unlock();
        }
    }

    @RequestMapping("/success")
    @ResponseBody
    public String success() throws UnsupportedEncodingException {
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = false;
        try {
            //验签
            signVerified = AlipaySignature.rsaCheckV1(params, alipay.getPublicKey(), alipay.getCharset(), alipay.getSignType()); //调用SDK验证签名
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }


        if (signVerified){
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
            //获取到订单号
            Indent indent = indentService.getMiddleId(out_trade_no);
            //判断订单号是否存在
            if (indent==null){
                //订单号如果不存在将商品数量加回来
                orderService.updateLimitNum2(indent.getMiddleId());
                return "订单号不存在";
            }
            //判断状态是否为2：订单已经过期
            if (indent.getStatus()==2){
                return "订单已过期";
            }
            //将状态改为1：支付成功，支付时间改为当前时间
            indentService.update(out_trade_no);
            return "交易成功！";
        }else {
            return "验证失败";
        }

    }

    @RequestMapping(value = "/index")
    public String payCoin(){
        return "index.html";
    }


}
